package com.coder.widget

import android.content.Context
import android.graphics.Point
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import androidx.customview.widget.ViewDragHelper
import timber.log.Timber

/**
 * @description 可拖拽子View的FrameLayout
 * @author yuhus
 * @date 2021/12/8 13:53
 */
class DragFrameLayout : FrameLayout {
    private var mDragView: View? = null
    private var mAutoBackView: View? = null
    private var mEdgeTrackerView: View? = null

    // 记录释放位置，解决MotionLayout嵌套问题
    private val mDragLastPos = Point()

    // 初始位置
    private val mAutoBackOriginPos = Point()

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )

    constructor(
        context: Context,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes)

    private val mDragHelper: ViewDragHelper by lazy {
        ViewDragHelper.create(this, 1f, object : ViewDragHelper.Callback() {
            override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
                if (releasedChild == mAutoBackView) {
                    mDragHelper.settleCapturedViewAt(mAutoBackOriginPos.x, mAutoBackOriginPos.y)
                    invalidate()
                }
                if (releasedChild == mDragView) {
                    mDragView?.let { mDragLastPos.set(it.left, it.top) }
                }
            }

            override fun onEdgeDragStarted(edgeFlags: Int, pointerId: Int) {
                Timber.d("edgeFlags=$edgeFlags")
                mEdgeTrackerView?.let { mDragHelper.captureChildView(it, pointerId) }
            }

            override fun getViewHorizontalDragRange(child: View): Int {
                return mDragHelper.touchSlop
            }

            override fun getViewVerticalDragRange(child: View): Int {
                return mDragHelper.touchSlop
            }

            override fun tryCaptureView(child: View, pointerId: Int): Boolean {
                // mEdgeTrackerView 禁止直接移动
                Timber.d("tryCaptureView= ${child == mDragView}")
                return child == mDragView || child == mAutoBackView
            }

            override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int {
                Timber.d("left=$left")
                return left
            }

            override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
                Timber.d("top=$top")
                return top
            }


        }).apply {
            setEdgeTrackingEnabled(ViewDragHelper.EDGE_ALL)
        }
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        Timber.d("onInterceptTouchEvent")
        return mDragHelper.shouldInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        Timber.d("onTouchEvent")
        mDragHelper.processTouchEvent(event)
        return true
    }

    override fun computeScroll() {
        if (mDragHelper.continueSettling(true)) {
            invalidate()
        }
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (!mDragLastPos.equals(0, 0)) {
            mDragView?.apply {
                Timber.d("mDragView offset")
                offsetLeftAndRight(mDragLastPos.x)
                offsetTopAndBottom(mDragLastPos.y)
            }
        }

        mAutoBackView?.let { mAutoBackOriginPos.set(it.left, it.top) }
        Timber.d("onLayout $mAutoBackOriginPos")
    }

    override fun onFinishInflate() {
        super.onFinishInflate()

        if (childCount > 0) {
            mDragView = getChildAt(0)
        }
        if (childCount > 1) {
            mAutoBackView = getChildAt(1)
        }

        if (childCount > 2) {
            mEdgeTrackerView = getChildAt(2)
        }

    }

}